﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Scripting;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;
using RelationalOperator = DlrBasic.Runtime.RelationalOperator;

namespace DlrBasic.Parser.Ast
{
    class RelationalOperators: BinaryExpressionList
    {
        static Dictionary<int, RelationalOperator> OperatorValues;

        static RelationalOperators()
        {
            OperatorValues = new Dictionary<int, RelationalOperator>();
            OperatorValues.Add(Operators.EqualId, RelationalOperator.Equality);
            OperatorValues.Add(Operators.NotEqualId, RelationalOperator.Inequality);
            OperatorValues.Add(Operators.LessThenId, RelationalOperator.LessThan);
            OperatorValues.Add(Operators.LessThenOrEqualId, RelationalOperator.LessThanOrEqualTo);
            OperatorValues.Add(Operators.GreaterThenId, RelationalOperator.GreaterThan);
            OperatorValues.Add(Operators.GreaterThenOrEqualId, RelationalOperator.GreaterThanOrEqualTo);
        }

        public RelationalOperators(SourceSpan span, DlrBasicExpression[] expressions, int[] operatorIds)
            : base(span, expressions, operatorIds)
        {
        }

        protected internal override Expression Generate(DlrBasicGenerator tg)
        {
            List<Expression> result = new List<Expression>();
            foreach (DlrBasicExpression expr in Expressions)
            {
                result.Add(expr.Generate(tg));
            }
            List<int> operators = new List<int>(this.OperatorIds);

            int i = 0;
            while (i < operators.Count)
            {
                RelationalOperator @operator = OperatorValues[operators[i]];

                System.Reflection.MethodInfo method;
                Expression converted1, converted2;

                TypeConversionUtils.FindMethodAndConvertOperands(typeof(Runtime.DlrBasicCompare),
                    "Compare", result[i], result[i + 1],
                    out method, out converted1, out converted2);

                Expression expr = Expression.Call(method,
                    Expression.Constant(@operator), converted1, converted2);

                operators.RemoveAt(i);
                result.RemoveAt(i); result.RemoveAt(i);
                result.Insert(i, expr);
            }

            return result[0];
        }
    }
}
